<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../res/vue.js"></script>
    <link rel="stylesheet" href="app.css"></link>
</head>
<body>
<script type="text/javascript">
</script>
<div id="app-1">
    <currency-input label="price" v-model="price"></currency-input>
    <currency-input label="shipping" v-model="shipping"></currency-input>
    <currency-input label="handling" v-model="handling"></currency-input>
    <currency-input label="discount" v-model="discount"></currency-input>
    <span>total:${{total}}</span>
</div>
</body>
<script type="text/javascript">
    Vue.component('currency-input',{
       template:'<span><span>{{label}}</span>' +
       '<span>$<input ref="currencyInput" v-bind:value="value"' +
       ' v-on:input="updateValue($event.target.value)"' +
       ' v-on:focus="selectAll" v-on:blur="formatValue"></span><br/></span>',
        props:{
           value:{
               type:Number,
               default:0
           },
            label:{
               type:String,
                default:''
            }
        },
        methods:{
            updateValue:function (value) {
                var result = currencyValidator.parse(value,this.value);
               if(result.warning){
                    this.$refs.currencyInput.value = result.value;
               }
               this.$emit('input',result.value);
           },
            formatValue:function () {
                this.$refs.currencyInput.value = currencyValidator.format(this.value);
            },
            selectAll:function (event) {
                setTimeout(function () {
                    event.target.select();
                },0)
            }
        }
    });
    var app = new Vue({
        el:'#app-1',
        data:{
            price:0,
            shipping:0,
            handling:'ff',
            discount:0,

        },
        computed:{
            total:function () {
                return ((
                    this.price*100 +
                        this.shipping * 100 +
                        this.handling * 100+
                        this.discount * 100
                )/100).toFixed(2)
            }
        }
    })
    var currencyValidator = {
        format: function (number) {
            return (Math.trunc(number * 100) / 100).toFixed(2)
        },
        parse: function (newString, oldNumber) {
            var CleanParse = function (value) {
                return { value: value }
            }
            var CurrencyWarning = function (warning, value) {
                return {
                    warning: warning,
                    value: value,
                    attempt: newString
                }
            }
            var NotAValidDollarAmountWarning = function (value) {
                return new CurrencyWarning(newString + ' is not a valid dollar amount', value)
            }
            var AutomaticConversionWarning = function (value) {
                return new CurrencyWarning(newString + ' was automatically converted to ' + value, value)
            }

            var newNumber = Number(newString)
            var indexOfDot = newString.indexOf('.')
            var indexOfE = newString.indexOf('e')

            if (isNaN(newNumber)) {
                if (
                    indexOfDot === -1 &&
                    indexOfE > 0 &&
                    indexOfE === newString.length - 1 &&
                    Number(newString.slice(0, indexOfE)) !== 0
                ) {
                    return new CleanParse(oldNumber)
                } else {
                    return new NotAValidDollarAmountWarning(oldNumber)
                }
            }

            var newCurrencyString = currencyValidator.format(newNumber)
            var newCurrencyNumber = Number(newCurrencyString)

            if (newCurrencyNumber === newNumber) {
                if (indexOfE !== -1 && indexOfE === newString.length - 2) {
                    return new AutomaticConversionWarning(newNumber)
                } else {
                    return new CleanParse(newNumber)
                }
            } else {
                return new NotAValidDollarAmountWarning(
                    newNumber > newCurrencyNumber
                        ? newCurrencyNumber
                        : oldNumber
                )
            }
        }
    }
</script>
</html>